package model

import (
	"errors"
	"gorm.io/gorm"
	"strings"
)

type CaseHistoryMeta struct {
	gorm.Model
	UserId uint `json:"user_id"`
}

type CaseHistory struct {
	CaseHistoryMeta
	CaseHistoryField
}

func (b *CaseHistory) Create(db *gorm.DB) error {
	return db.Create(b).Error
}

func (b *CaseHistory) Get(db *gorm.DB) error {
	return db.First(b).Error
}

func (b *CaseHistory) Save(db *gorm.DB) error {
	return db.Save(b).Error
}

type CaseHistoryField struct {
	Gender    Gender  `json:"gender"`
	Age       int     `json:"age"`
	Height    float64 `json:"height"`
	Weight    float64 `json:"weight"`
	DmType    DmType  `json:"dmType"`
	Diagnosis int     `json:"diagnosis"`
	Note      string  `json:"note"`
}

type CaseHistoryView struct {
	Gender string `json:"gender"`
	DmType string `json:"dmType"`
	CaseHistoryField
}

func FormatCaseHistoryView(ch *CaseHistory) CaseHistoryView {
	return CaseHistoryView{
		Gender:           FormatGender(ch.Gender),
		DmType:           FormatDmType(ch.DmType),
		CaseHistoryField: ch.CaseHistoryField,
	}
}

const (
	GenderNull = iota
	Female
	Male
	MalGender = -1
)

type Gender int

func (g *Gender) UnmarshalJSON(data []byte) error {
	raw := strings.Trim(string(data), "\"")
	*g = ParseGender(raw)
	if *g == MalGender {
		return errors.New("invalid gender")
	}
	return nil
}

func ParseGender(t string) Gender {
	switch t {
	case "":
		return GenderNull
	case "女":
		return Female
	case "男":
		return Male
	}

	return MalGender
}

func FormatGender(t Gender) string {
	switch t {
	case Female:
		return "女"
	case Male:
		return "男"
	}

	return ""
}

const (
	DmTypeNull = iota
	T1DM
	T2DM
	MalDmType = -1
)

type DmType int

func (t *DmType) UnmarshalJSON(data []byte) error {
	raw := strings.Trim(string(data), "\"")
	*t = ParseDmType(raw)
	if *t == MalDmType {
		return errors.New("invalid dm type")
	}
	return nil
}

func ParseDmType(t string) DmType {
	switch t {
	case "":
		return DmTypeNull
	case "T1DM":
		return T1DM
	case "T2DM":
		return T2DM
	}

	return MalDmType
}

func FormatDmType(t DmType) string {
	switch t {
	case T1DM:
		return "T1DM"
	case T2DM:
		return "T2DM"
	}

	return ""
}
